package com.poet.df.xml;

import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sql.DataSource;

import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import antlr.collections.impl.LList;

import com.poet.df.dbinfo.DbInfo;
import com.poet.df.dbinfo.pojo.Column;
import com.poet.df.dbinfo.pojo.ForeignKey;
import com.poet.df.dbinfo.pojo.PrimaryKey;
import com.poet.df.dbinfo.pojo.Table;
import com.poet.df.xml.cm.ColumnMappings;
import com.poet.df.xml.elementhandler.XmlElementHandler;
import com.poet.df.xml.pojo.HtmlForm;
import com.poet.df.xml.pojo.HtmlFormItem;

@Component
public class DynamicFormXmlReader implements InitializingBean {

	public Map<String, XmlElementHandler> xmlHandlers = new HashMap<String, XmlElementHandler>();

	@Resource
	public XmlElementHandler[] handlers;

	@Resource
	private DbInfo dbInfo;

	@PostConstruct
	public void init() {

	}

	/**
	 * 根据表名称获取Form
	 * @param tableName
	 * @return
	 */
	public HtmlForm getForm(String tableName){
		HtmlForm result = null;
		for(HtmlForm form : this.forms.values()){
			if(form.getTableName().equals(tableName)){
				result = form;
				break;
			}
		}
		return result;
	}
	
	public void setXmlHandlers(Map<String, XmlElementHandler> xmlHandlers) {
		this.xmlHandlers = xmlHandlers;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		if (handlers == null)
			return;
		for (XmlElementHandler h : handlers) {
			xmlHandlers.put(h.getElementName(), h);
		}
		// 首先从数据表中构造Form
		readFromTable();
		// 读取xml中的自定义配置
		readFormXml();
		// 获取外键列数据
		fetchForeignKeyData();
	}

	private final String FILE_NAME = "/forms/form.xml";

	private Map<String, HtmlForm> forms = new HashMap<String, HtmlForm>();

	private void handleElement(Element element, HtmlForm form) {
		for (Element e : (List<Element>) element.elements()) {
			XmlElementHandler handler = xmlHandlers.get(e.getName());
			handler.handlerElement(e, form);
			handleElement(e, form);
		}
	}

	@Resource
	private DataSource dataSource;

	/**
	 * 临时编写，生产环境需要修改
	 */
	private void fetchForeignKeyData() {

		for (HtmlForm form : this.forms.values()) {
			for (HtmlFormItem item : form.getItems()) {
				if (!item.isFk())
					continue;

				String tableName = item.getPkTable();
				String pkColumn = item.getPkColumn();
				String pkDisplayColumn = item.getFkDisplayColumn();

				String sql = "select ?,? from ?";
				sql = sql.replaceFirst("[?]", pkColumn);
				sql = sql.replaceFirst("[?]", pkDisplayColumn);
				sql = sql.replaceFirst("[?]", tableName);

				System.out.println(sql);
				Map<String, String> map = item.getFkValues();
				try (Connection conn = dataSource.getConnection();
						PreparedStatement pst = conn.prepareStatement(sql);
						ResultSet rs = pst.executeQuery()) {
					
					while(rs.next()){
						map.put(rs.getString(1),rs.getString(2));
					}
					
				} catch (Exception e) {e.printStackTrace();}

			}
		}

	}

	/**
	 * 读取文件
	 */
	private void readFormXml() {
		InputStream in = getFormFileStream();
		SAXReader reader = new SAXReader();
		try {

			Document doc = reader.read(in);

			Element root = doc.getRootElement();

			List<Element> elements = root.elements();

			HtmlForm form = null;
			for (Element e : elements) {
				String id = e.attributeValue("tableName");
				form = this.forms.get(id);
				if (form == null) {
					form = new HtmlForm();
				}
				List<Attribute> attributes = e.attributes();
				for (Attribute attr : attributes) {
					String attrName = attr.getName();
					String attrValue = attr.getValue();
					try {
						BeanUtils.setProperty(form, attrName, attrValue);
					} catch (IllegalAccessException | InvocationTargetException ex) {
						ex.printStackTrace();
					}
				}
				handleElement(e, form);
				this.forms.put(form.getId(), form);
			}
			int x = 0;

		} catch (DocumentException e) {
			e.printStackTrace();
		}

	}

	@Resource
	private ColumnMappings columnMappings;

	private void readFromTable() {
		List<Table> tables = dbInfo.getAllTables();
		HtmlForm form = null;
		HtmlFormItem item = null;
		for (Table table : tables) {
			form = new HtmlForm();
			form.setId(table.getTableName());
			form.setName(table.getTableName());
			form.setTableName(table.getTableName());

			// process primary key
			Collection<PrimaryKey> pks = table.getPrimaryKeys().values();
			for (PrimaryKey pk : pks) {
				// 主键非自增
				if (!pk.getIsAutoIncrement()) {
					item = new HtmlFormItem();
					item.setColumnName(pk.getColumnName());
					String mappingKey = table.getTableName() + "."
							+ pk.getColumnName();
					item.setInputName(mappingKey);
					item.setIsDisplay("true");
					item.setIsNullable("false");
					item.setLabel(columnMappings.getLabel(mappingKey,
							pk.getRemarks()));
					form.getItems().add(item);
				} else {
					item = new HtmlFormItem();
					item.setColumnName(pk.getColumnName());
					String mappingKey = table.getTableName() + "."
							+ pk.getColumnName();
					item.setInputName(mappingKey);
					item.setIsDisplay("false");
					item.setIsNullable("true");
					item.setLabel(columnMappings.getLabel(mappingKey,
							pk.getRemarks()));
					item.setTagType("hidden");
					form.getItems().add(item);
				}
			}

			// process foreign key
			Collection<ForeignKey> foreignKeys = table.getForeignKeys()
					.values();
			for (ForeignKey fk : foreignKeys) {
				item = new HtmlFormItem();
				item.setColumnName(fk.getColumnName());
				String mappingKey = table.getTableName() + "."
						+ fk.getPkTableName() + "." + fk.getColumnName();
				item.setFkDisplayColumn(fk.getPkColumnName());
				item.setHtmlTag("select");
				item.setInputName(mappingKey);
				item.setIsDisplay("true");
				item.setPkColumn(fk.getPkColumnName());
				item.setPkTable(fk.getPkTableName());
				item.setIsNullable(fk.getIsNullable() == true ? "true"
						: "false");
				item.setLabel(columnMappings.getLabel(mappingKey,
						fk.getRemarks()));
				item.setTagType("");
				item.setIsFk(true);
				form.getItems().add(item);
			}

			// process other column
			for (Column col : table.getColumns().values()) {
				if (col.getClass() == PrimaryKey.class
						|| col.getClass() == ForeignKey.class)
					continue;

				item = new HtmlFormItem();
				item.setColumnName(col.getColumnName());
				String mappingKey = table.getTableName() + "."
						+ col.getColumnName();
				item.setInputName(mappingKey);
				item.setIsDisplay("true");
				item.setIsNullable(col.getIsNullable() == true ? "true"
						: "false");
				item.setLabel(columnMappings.getLabel(mappingKey,
						col.getRemarks()));

				form.getItems().add(item);

			}

			this.forms.put(form.getId(), form);
		}
	}

	private InputStream getFormFileStream() {
		return Thread.currentThread().getContextClassLoader()
				.getResourceAsStream(FILE_NAME);
	}

}
